﻿
using Bettzueche.RLLibrary.Types;
using System;
namespace RLProject1.Model {
    /// <summary>
    /// Enum, für Bewegungen in einer Rasterwelt
    /// </summary>
    public enum GridActionTypes {
        N,
        NO,
        O,
        SO,
        S,
        SW,
        W,
        NW
    }

    /// <summary>
    /// Bewegung in einer Rasterwelt.
    /// <para>
    /// Unterstützt impliziten Cast nach int und expliziten Cast von int nach GridAction.
    /// </para>
    /// </summary>
    public struct GridAction : IAction {
        public GridActionTypes Direction;
        public static readonly GridAction NORTH = new GridAction { Direction = GridActionTypes.N };
        public static readonly GridAction NORTHEAST = new GridAction { Direction = GridActionTypes.NO };
        public static readonly GridAction EAST = new GridAction { Direction = GridActionTypes.O };
        public static readonly GridAction SOUTHEAST = new GridAction { Direction = GridActionTypes.SO };
        public static readonly GridAction SOUTH = new GridAction { Direction = GridActionTypes.S };
        public static readonly GridAction SOUTHWEST = new GridAction { Direction = GridActionTypes.SW };
        public static readonly GridAction WEST = new GridAction { Direction = GridActionTypes.W };
        public static readonly GridAction NORTHWEST = new GridAction { Direction = GridActionTypes.NW };

        /// <summary>
        /// Implizieter Cast GridAction -> Int32.
        /// </summary>
        /// <param name="a">Action</param>
        /// <returns>korrespondierende Int32 zu GridAction.Direction</returns>
        public static implicit operator int(GridAction a) {
            return (int)a.Direction;
        }
        /// <summary>
        /// Grids the action.
        /// </summary>
        /// <param name="i"></param>
        /// <returns>GridAction mit Direction = i'tes <see cref="GridActionTypes">GridActionType</see>.</returns>
        /// <exception cref="System.InvalidCastException">Für die spezifizierte Zahl gibt es keine korrespondierrende GridAction.</exception>
        public static explicit operator GridAction(int i) {
            GridActionTypes[] types = (GridActionTypes[])Enum.GetValues(typeof(GridActionTypes));
            if (i < 0 || i >= types.Length)
                throw new InvalidCastException("Cannot cast " + i + "to a corresponding GridAction. Only values between 0 and " + types.Length + "are supported.");
            return new GridAction{ Direction = types[i] };
        }
        /// <summary>
        /// Implizieter Cast GridActionTypes -> GridAction
        /// </summary>
        /// <param name="actionType">GridActionTypes</param>
        /// <returns>GridAction</returns>
        public static implicit operator GridAction(GridActionTypes actionType) {
            switch (actionType) {
                case GridActionTypes.N:
                    return GridAction.NORTH;
                case GridActionTypes.NO:
                    return GridAction.NORTHEAST;
                case GridActionTypes.O:
                    return GridAction.EAST;
                case GridActionTypes.SO:
                    return GridAction.SOUTHEAST;
                case GridActionTypes.S:
                    return GridAction.SOUTH;
                case GridActionTypes.SW:
                    return GridAction.SOUTHWEST;
                case GridActionTypes.W:
                    return GridAction.WEST;
                case GridActionTypes.NW:
                    return GridAction.NORTHWEST;
                default:
                    return GridAction.NORTH;
            }
        }

        public override string ToString() {
            return "GridAction[" + Direction.ToString() + "]";
        }
    }

    /// <summary>
    /// Zustand in einer Rasterwelt.
    /// </summary>
    /// <remarks>
    /// Es ist eine implizite Zuweisung zwischen GridState und Int32 möglich:
    /// <code>
    /// GridState state = 0;
    /// int i = state;
    /// </code>
    /// </remarks>
    public struct GridState : IStateID {
        public GridState(int id) {
            _id = id;
        }

        public static implicit operator int(GridState s) {
            return s.ID;
        }

        public static implicit operator GridState(int i) {
            return new GridState { ID = i };
        }

        public override string ToString() {
            return "GridState[" + ID + "]";
        }

        #region ITypeID Members
        int _id;
        public int ID { 
            get { return _id; }
            set { _id = value; }
        }

        #endregion
    }
}
